﻿using Gargoyle.Roton;
using System;
using System.Collections.Generic;
using System.Text;

namespace Gargoyle.ZZT
{
    static class Draw
    {
        public static byte[] lineChars =
        {
            0xF9, 0xD0, 0xD2, 0xBA,
            0xB5, 0xBC, 0xBB, 0xB9,
            0xC6, 0xC8, 0xC9, 0xCC,
            0xCD, 0xCA, 0xCB, 0xCE
        };

        public static byte[] starChars =
        {
            0xB3, 0x2F, 0xC4, 0x5C
        };

        public static byte[] transporterHChars =
        {
            0x28, 0x3C, 0x28, 0xB3,
            0x29, 0x3E, 0x29, 0xB3
        };

        public static byte[] transporterVChars =
        {
            0x5E, 0x7E, 0x5E, 0x2D,
            0x76, 0x5F, 0x76, 0x2D
        };

        public static byte[] webChars =
        {
            0xFA, 0xB3, 0xB3, 0xB3,
            0xC4, 0xD9, 0xBF, 0xB4,
            0xC4, 0xC0, 0xDA, 0xC3,
            0xC4, 0xC1, 0xC2, 0xC5
        };

        public static AnsiChar BlinkWall(Game g, Location location)
        {
            return new AnsiChar(0xCE, g.GetColorAt(location));
        }

        public static AnsiChar Bomb(Game g, Location location)
        {
            byte color = g.GetColorAt(location);
            Thing thing = g.GetThingAt(location);

            if (thing.P1 > 1)
                return new AnsiChar((byte)(0x30 + thing.P1), color);
            else
                return new AnsiChar(0x0B, color);
        }

        public static AnsiChar Clockwise(Game g, Location location)
        {
            byte color = g.GetColorAt(location);

            switch ((g.State.Tick / g.Elements[ElementID.Clockwise].Cycle) % 4)
            {
                case 0:
                    return new AnsiChar(0xB3, color);
                case 1:
                    return new AnsiChar(0x2F, color);
                case 2:
                    return new AnsiChar(0xC4, color);
                default:
                    return new AnsiChar(0x5C, color);
            }
        }

        public static AnsiChar Counter(Game g, Location location)
        {
            byte color = g.GetColorAt(location);

            switch ((g.State.Tick / g.Elements[ElementID.Counter].Cycle) % 4)
            {
                case 3:
                    return new AnsiChar(0xB3, color);
                case 2:
                    return new AnsiChar(0x2F, color);
                case 1:
                    return new AnsiChar(0xC4, color);
                default:
                    return new AnsiChar(0x5C, color);
            }
        }

        public static AnsiChar DragonPup(Game g, Location location)
        {
            byte color = g.GetColorAt(location);

            switch (g.State.Tick & 3)
            {
                case 0:
                case 2:
                    return new AnsiChar(0x94, color);
                case 1:
                    return new AnsiChar(0xA2, color);
                default:
                    return new AnsiChar(0x95, color);
            }
        }

        public static AnsiChar Duplicator(Game g, Location location)
        {
            byte color = g.GetColorAt(location);
            Thing thing = g.GetThingAt(location);

            switch (thing.P1)
            {
                case 1:
                    return new AnsiChar(0xFA, color);
                case 2:
                    return new AnsiChar(0xF9, color);
                case 3:
                    return new AnsiChar(0xF8, color);
                case 4:
                    return new AnsiChar(0x6F, color);
                case 5:
                    return new AnsiChar(0x4F, color);
                default:
                    return new AnsiChar(0xFA, color);
            }
        }

        public static AnsiChar Line(Game g, Location location)
        {
            int adjacent = g.GetAdjacents(location, g.Elements.IndexOf(g.Elements[ElementID.Line]));
            return new AnsiChar(lineChars[adjacent], g.GetColorAt(location));
        }

        public static AnsiChar Object(Game g, Location location)
        {
            Thing thing = g.GetThingAt(location);
            return new AnsiChar(thing.P1, g.GetColorAt(location));
        }

        public static AnsiChar Pusher(Game g, Location location)
        {
            byte color = g.GetColorAt(location);
            Thing thing = g.GetThingAt(location);

            if (thing.XStep == 1)
                return new AnsiChar(0x10, color);
            else if (thing.XStep == -1)
                return new AnsiChar(0x11, color);
            else if (thing.YStep == -1)
                return new AnsiChar(0x1E, color);
            else
                return new AnsiChar(0x1F, color);
        }

        public static AnsiChar SpinningGun(Game g, Location location)
        {
            byte color = g.GetColorAt(location);

            switch (g.State.Tick % 8)
            {
                case 0:
                case 1:
                    return new AnsiChar(0x18, color);
                case 2:
                case 3:
                    return new AnsiChar(0x1A, color);
                case 4:
                case 5:
                    return new AnsiChar(0x19, color);
                default:
                    return new AnsiChar(0x1B, color);
            }
        }

        public static AnsiChar Star(Game g, Location location)
        {
            unchecked
            {
                byte color = g.GetColorAt(location);
                color++;
                if (color > 15)
                    color = 9;
                g.SetColorAt(location, color);
            }
            return new AnsiChar(starChars[g.State.Tick % 4], g.GetColorAt(location));
        }

        public static AnsiChar Stone(Game g, Location location)
        {
            return new AnsiChar((byte)(0x41 + g.RandomNumber(0x1A)), g.GetColorAt(location));
        }

        public static AnsiChar Transporter(Game g, Location location)
        {
            Thing thing = g.GetThingAt(location);
            byte color = g.GetColorAt(location);
            int index;

            if (thing.XStep == 0)
            {
                if (thing.Cycle > 0)
                    index = ((g.State.Tick / thing.Cycle) % 4);
                else
                    index = 0;
                index += (thing.YStep << 1) + 2;
                return new AnsiChar(transporterVChars[index], color);
            }
            else
            {
                if (thing.Cycle > 0)
                    index = ((g.State.Tick / thing.Cycle) % 4);
                else
                    index = 0;
                index += (thing.XStep << 1) + 2;
                return new AnsiChar(transporterHChars[index], color);
            }
        }

        public static AnsiChar Web(Game g, Location location)
        {
            int adjacent = g.GetAdjacents(location, g.Elements.IndexOf(g.Elements[ElementID.Web]));
            return new AnsiChar(webChars[adjacent], g.GetColorAt(location));
        }
    }
}